#include <usr/libsodium.h>
#include <usr/shellusr.h>
#include <shell/teclado.h>


 extern unsigned int uiModoMemoria;
 char stBuffer[TAMANIO_BUFFER_SHELL];
 char stCmd[TAMANIO_BUFFER_SHELL];
 char stCmdTemp[TAMANIO_BUFFER_SHELL];
 char stAsignacion[TAMANIO_BUFFER_SHELL];
 char stPrintChar[2];
 int  iCaracteresIngresados = 0;
 int  iTerminal = TERM_SODIUM;

int main(){
	
 char cCaracter;
 int iCaracterLeido;
 int iArgumento, iArgumento2;
 int iCmdReconocido;
 int i;

 iFnImprimir("\nCmd>");
   
  // Loop principal del Shell
 while (1) 
  {
    iCaracterLeido = iFnLeerCaracter(&cCaracter);
    if (iCaracterLeido != -1) // Si leyó correctamente sigue, sino vuelve a leer. La espera activa es del lado usuario.
      {

         switch(iCaracterLeido)
          {   

            case TECLA_F1:
                if(iTerminal == TERM_LOG)
                 {
                   iFnSodiumCallgate(__FC_LOG,0,0);
                   iTerminal = TERM_SODIUM;
                 }
                break;

            case TECLA_F2:
                if(iTerminal == TERM_SODIUM)
                 {
                   iFnSodiumCallgate(__FC_LOG,0,0);
                   iTerminal = TERM_LOG;
                 }
                break;

            case TECLA_BACKSPACE:
              
                if(iCaracteresIngresados > 0)
                  {
                    stPrintChar[0] = (char)iCaracterLeido;
                    stPrintChar[1] = '\0';
                    iFnImprimir("%s",stPrintChar);
                    iCaracteresIngresados--;
		    stBuffer[iCaracteresIngresados] = '\0';
                  }
                break;

            case TECLA_ENTER:
                iCmdReconocido = 0;
                if(iCaracteresIngresados > 0)
                  {
						iFnObtenerCmd(stCmd, &iArgumento, &iArgumento2);
						// Comando Log
						if(iFnEsCmdShell("log")) {
							 iFnSodiumCallgate(__FC_LOG,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando Ayuda
						if(iFnEsCmdShell("ayuda")) {
							 vFnMenuAyuda();
							 iCmdReconocido = 1;
						   }
						// Comando cls
						if(iFnEsCmdShell("cls")) {
							 iFnSodiumCallgate(__FC_CLS,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando gdt
						if(iFnEsCmdShell("gdt")) {
							 iFnSodiumCallgate(__FC_GDT,iArgumento,0);
							 iCmdReconocido = 1;
						   }
						// Comando gdtall
						if(iFnEsCmdShell("gdtall")) {
							 for(i=0;i<20;i++)
							   {
								 iFnImprimir("\nPosicion de GDT: %d",i);
								 iFnSodiumCallgate(__FC_GDT,i,0);
								 PAUSA_BREAK;
							   }
							 iCmdReconocido = 1;
						   }
						// Comando verShm
						if(iFnEsCmdShell("verShm")) {
							 iFnSodiumCallgate(__FC_VERSHM,iArgumento,0);
							 iCmdReconocido = 1;
						   }
						// Comando verSem
						if(iFnEsCmdShell("verSem")) {
							 iFnSodiumCallgate(__FC_VERSEM,iArgumento,0);
							 iCmdReconocido = 1;
						   }
						// Comando sysgetpid
						if(iFnEsCmdShell("sysgetpid")) {
							 iFnSodiumCallgate(__FC_GETPID,iArgumento,0);
							 iCmdReconocido = 1;
						   }
						// Comando sysgetppid
						if(iFnEsCmdShell("sysgetppid")) {
							 iFnSodiumCallgate(__FC_GETPPID,iArgumento,0);
							 iCmdReconocido = 1;
						   }
						// Comando segs
						if(iFnEsCmdShell("segs")) {
							 iFnSodiumCallgate(__FC_SEGS,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando mem
						if(iFnEsCmdShell("mem")) {
							 iFnSodiumCallgate(__FC_MEM,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando reboot
						if(iFnEsCmdShell("reboot")) {
							 iFnImprimir("Reiniciando el sistema...");
							 iFnSodiumCallgate(__FC_REBOOT,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando bitmap
						if(iFnEsCmdShell("bitmap")) {
							iFnSodiumCallgate(__FC_BITMAP,0,0);
							iCmdReconocido = 1;
						}
						//Comando idt
						if(iFnEsCmdShell("idt")) {
							 iFnSodiumCallgate(__FC_IDT,iArgumento,0);
							 iCmdReconocido = 1;
						}
						//Comando idtall
						if(iFnEsCmdShell("idtall")) {
							 for(i=0;i<512;i++)
							 {
								 iFnImprimir("\nPosicion de IDT: %d",i);
										 iFnSodiumCallgate(__FC_IDT,i,0);
										 PAUSA_BREAK2;
							 }
							iCmdReconocido = 1;
						}
						// Comando yield
						if(iFnEsCmdShell("yield")) {
							 iFnImprimir("\nEl shell cede la ejecucion\n");
							 iFnSodiumCallgate(__FC_YIELD,0,0);
							 iCmdReconocido = 1;
						}
						// Comando set
						if(iFnEsCmdShell("set")) {
							 iFnEnvListarEnviroment();
							 iCmdReconocido = 1;
						}
						 // Comando pag
						 if(iFnEsCmdShell("pag")) {
							 iFnSodiumCallgate(__FC_PAG,iArgumento,0);
							 iCmdReconocido = 1;
						}
						// Comando tss
						if(iFnEsCmdShell("tss")) {
							 iFnSodiumCallgate(__FC_TSS,iArgumento,0);
							 iCmdReconocido = 1;
						}
						// Comando stack
						if(iFnEsCmdShell("stack")) {
							 iFnSodiumCallgate(__FC_STACK,iArgumento,iArgumento2);
							 iCmdReconocido = 1;
						}
						// Comando listporc
						if(iFnEsCmdShell("listporc")) {
							 iFnSodiumCallgate(__FC_LISTPORC,0,0);
							 iCmdReconocido = 1;
						}
						// Comando borrarpf
						if(iFnEsCmdShell("borrarpf")) {
							 iFnSodiumCallgate(__FC_BORRARPF,0,0);
							 iCmdReconocido = 1;
						}
						// Comando exec
						if(iFnEsCmdShell("exec")) {
							 iFnSodiumCallgate(__FC_EXEC,iArgumento,iArgumento2);
							 iCmdReconocido = 1;
						}
						// Comando planif
						if(iFnEsCmdShell("planif")) {
							 vFnMenuPlanif();
							 iCmdReconocido = 1;
						}
						//Inicio modificacion Fernando***********
						//***************************************
						// Comando leer	
						if(iFnEsCmdShell("leer")) {
							 iFnTomaPrimerPara();
							 iFnSodiumCallgate(__FC_LEER,(int)stCmd,0);
							 iCmdReconocido = 1;
						}
						// Comando dump
						if(iFnEsCmdShell("dump")) {
							 vFnMenuDumpUsr(iArgumento,iArgumento2);
							 //iFnSodiumCallgate(__FC_DUMP,iArgumento,iArgumento2);
							 iCmdReconocido = 1;
						}
						// Comando cd
						if(iFnEsCmdShell("cd")) {
							 iFnTomaPrimerPara();
							 iFnSodiumCallgate(__FC_CD,(int)stCmd,0);
							 iCmdReconocido = 1;
						}
						// Comando ls
						if(iFnEsCmdShell("ls")) {
							 iFnTomaPrimerPara();
							 iFnSodiumCallgate(__FC_LS,(int)stCmd,0);
							 iCmdReconocido = 1;
						}
						// Comando listaesp
						if(iFnEsCmdShell("listaesp")) {
							 iFnTomaPrimerPara();
							 iFnSodiumCallgate(__FC_LISTAESP,0,0);
							 iCmdReconocido = 1;
						}
						// Comando rm
						if(iFnEsCmdShell("rm")) {
							 iFnTomaPrimerPara();
							 iFnSodiumCallgate(__FC_RM,(int)stCmd,0);
							 iCmdReconocido = 1;
						}
						// Comando write
						if(iFnEsCmdShell("write")) {
							 char stAux[TAMANIO_BUFFER_SHELL];
							 iFnTomaPrimerPara();
									 iFnTomaNParametro(2,stAux);
							 iFnSodiumCallgate(__FC_WRITE,(int)stCmd,(int)stAux);
							 iCmdReconocido = 1;
						}
						// Comando kill
						if(iFnEsCmdShell("kill")) {
							iFnSodiumCallgate(__FC_KILL,iArgumento,0);
							iCmdReconocido = 1;
						}
						// Comando syskill
						if(iFnEsCmdShell("syskill")) {
							if (iArgumento != 0) {
								if (iArgumento2 != 0) {
									iFnImprimir("\n Enviando la sig %d al proceso %d...",iArgumento2,iArgumento);

									if (iFnSodiumCallgate(__FC_SYSK,iArgumento,iArgumento2))
										iFnImprimir("ERROR (PID o SIG invalido)");
									else
										iFnImprimir("OK");
								} 
								else {
									iFnImprimir("\n Error, falta el numero de sig (ver ayuda)");
								}
							} 
							else {
								iFnImprimir("\n uso: syskill PID SIG");
								iFnImprimir("\n SIG: ");
								iFnImprimir("\n  SIGFPE  ");
								iFnImprimirNumero(SIGFPE);
								iFnImprimir("\n  SIGSEGV ");
								iFnImprimirNumero(SIGSEGV);
								iFnImprimir("\n  SIGINT  ");
								iFnImprimirNumero(SIGINT);
								iFnImprimir("\n  SIGSTOP ");
								iFnImprimirNumero(SIGSTOP);
								iFnImprimir("\n  SIGCONT ");
								iFnImprimirNumero(SIGCONT);
								iFnImprimir("\n  SIGKILL ");
								iFnImprimirNumero(SIGKILL);
								iFnImprimir("\n  SIGTERM ");
								iFnImprimirNumero(SIGTERM);
							}
							iCmdReconocido = 1;
						}
						//Fin modificacion Fernando**************
								//***************************************

						// Comando check
						if(iFnEsCmdShell("check")) {	//Agregar [en un futuro] para q reciba 3er parametro.
							 char stAux[TAMANIO_BUFFER_SHELL];
							 char stAux2[TAMANIO_BUFFER_SHELL];
							 int iAux[2];
							 iFnTomaPrimerPara();
							 iFnTomaNParametro(2,stAux);
							 iFnTomaNParametro(3,stAux2);
							 iAux[0]=(int)stAux;
							 iAux[1]=(int)stAux2;
							 iFnSodiumCallgate(__FC_CHECK,(int)stCmd,iAux);
							 iCmdReconocido = 1;
						   }
						// Comando syswaitpid
						if(iFnEsCmdShell("syswaitpid")) {
							 iFnSodiumCallgate(__FC_WAITPID,iArgumento,0);
							 iCmdReconocido = 1;
						   }
						// Comando lote
						if(iFnEsCmdShell("lote")) {
							 char stAux[TAMANIO_BUFFER_SHELL];
							 char stAux2[TAMANIO_BUFFER_SHELL];
							 int iAux[2];
							 iFnTomaPrimerPara();
							 iFnTomaNParametro(2,stAux);
							 iFnTomaNParametro(3,stAux2);
							 iAux[0]=(int)stAux;
							 iAux[1]=(int)stAux2;
							 iFnSodiumCallgate(__FC_LOTE,(int)stCmd,iAux);
							 iCmdReconocido = 1;
						   }
						// Comando pcb
						if(iFnEsCmdShell("pcb")) {
							 iFnSodiumCallgate(__FC_PCB,iArgumento,0);
							 iCmdReconocido = 1;
						   }
						// Comando idle
						if(iFnEsCmdShell("idle")) {
							 iFnFuncionIdle();
							 iCmdReconocido = 1;
						   }
						// Comando desc (devuelve el contenido de los descriptores para un PID dado)
						if(iFnEsCmdShell("desc")) {
							 iFnTomaPrimerPara();
							 vFnMenuDescUsr((int)stCmd);
						   //iFnSodiumCallgate(__FC_DESC,(int)stCmd,0);
							 iCmdReconocido = 1;
						   }
						// Comando ejecutar
						if(iFnEsCmdShell("ejecutar")) {
							 iFnTomaPrimerPara();
							 iFnSodiumCallgate(__FC_EJECUTAR,(int)stCmd,0);
							 iCmdReconocido = 1;
						   }
						// Comando exit
						if(iFnEsCmdShell("exit")) {
							return 0;
						   }
						// Comando fd
						if(iFnEsCmdShell("fd")) {
							 iFnSodiumCallgate(__FC_FD,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando sumafpu
						if(iFnEsCmdShell("sumafpu")) {
							 char stAux[TAMANIO_BUFFER_SHELL];
							 iFnTomaPrimerPara();
							 iFnTomaNParametro(2,stAux);
							 iFnSodiumCallgate(__FC_SUMAFPU,(int)stCmd,(int)stAux);
							 iCmdReconocido = 1;
						   }
						// Comando ver
						if(iFnEsCmdShell("ver")) {
							 iFnSodiumCallgate(__FC_VER,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando listpart
						if(iFnEsCmdShell("listpart")) {
							 iFnSodiumCallgate(__FC_LISTPART,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando resetpf
						if(iFnEsCmdShell("resetpf")) {
							 iFnSodiumCallgate(__FC_RESETPF,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando winm
						if(iFnEsCmdShell("winm")) {
							 iFnSodiumCallgate(__FC_WINM,0,0);
							 iCmdReconocido = 1;
						   }
						// Comando interval
						if(iFnEsCmdShell("interval")) {
							iFnSodiumCallgate(__FC_INTER,0,0);
							iCmdReconocido = 1;
							}
						// Comando cambiateclado
						if(iFnEsCmdShell("cambiateclado")) {
							iFnSodiumCallgate(__FC_CAMB,iArgumento,0);
							iCmdReconocido = 1;
							}
						// Comando cambiateclado
						if(iFnEsCmdShell("agregarpf")) {
										 iFnTomaPrimerPara();
							iFnSodiumCallgate(__FC_AGREGARPF,(int)stCmd,0);
							iCmdReconocido = 1;
							}
						// Si no se trata de un comando reconocido, puede ser
						// Una asignacion del tipo VARIABLE=VALOR para ser guardada en el enviroment
						// o el nombre de un binario a ejecutar
						if(iCmdReconocido == 0) 
						  {
						    // Evaluamos si es o no una asignacion.
							i = 0;
							while(stCmd[i] != '\0' && stCmd[i] != ' ' && stCmd[i] != '=') i++;
							if(stCmd[i] == '=') // Se trata de una asignacion
							 {
							   i = 0;
							   while(stCmd[i] != ' ' && stCmd[i] != '\0') { stAsignacion[i] = stCmd[i]; i++;}
							   stAsignacion[i] = '\0';
							   // Agregamos la asignacion al enviroment de usuario en el Heap
							   if(iFnEnvSet(stAsignacion) == -1) iFnImprimir("\nShell: No se pudo agregar la asignacion al Enviroment.");
							 }
						    else // Ya sabemos que no es una asignacion así que el usuario solicita la ejecucion de un binario
							 {
								iFnMayusculas(stCmd);
								//iFnImprimir("\nEjecutando ");
								//iFnImprimir("%s",stCmd);
								//iFnImprimir("...");
								iFnEjecutarBinario(stCmd, iArgumento); // argv +1 es envp.
							}
						  }
			

						stBuffer[0] = '\0';
					}
					
				for(i = 0; i < 255; i++){ stCmd[i] = '\0'; stBuffer[i] = '\0'; stCmdTemp[i] = '\0';}
				iCaracteresIngresados = 0;
				iFnImprimir("\nCmd>");
                break;

   case TECLA_TAB:
                //iFnSodiumCallgate(__FC_LOG,0,0);
                vFnAutocompletar();
                break;

               
    default:
				if(iTerminal == TERM_SODIUM && !(iCaracterLeido == TECLA_ARR || iCaracterLeido == TECLA_ABA || iCaracterLeido == TECLA_IZQ || iCaracterLeido == TECLA_DER ) )
					 {
							if(iCaracterLeido == '?') iCaracterLeido = '='; // Solucion temporal para el problema del =
				stBuffer[iCaracteresIngresados] = (char)iCaracterLeido;
					stPrintChar[0] = stBuffer[iCaracteresIngresados];
					stPrintChar[1] = '\0';
					iCaracteresIngresados++;
					stBuffer[iCaracteresIngresados] = '\0';
					iFnImprimir("%s",stPrintChar);
					 }
				if(iTerminal == TERM_LOG)
					 {
				iFnSodiumCallgate(__FC_LOGFC,iCaracterLeido,0);
					 }

              
          } // Fin Switch
      } // Fin If(iCaracterLeido != -1)
   } // Fin While
 
 return -1; // -1: No debería salir jamas del loop si no es con un exit.

}

/**
 * @brief Pasa a mayusculas las letras minusculas de una cadena
 * @param stCadena Cadena a convertir
 * @date 23/05/2009
 */
int iFnMayusculas(char *stCadena)
 {
   int i;
   i = 0;
   while (stCadena[i] != '\0')
     {
      if(((int)stCadena[i] >= 97) && ((int)stCadena[i] <= 122)) stCadena[i] -= 32;
      i++;
     }
    stCadena[i++] = '.';
    stCadena[i++] = 'B';
    stCadena[i++] = 'I';
    stCadena[i++] = 'N';
    stCadena[i] = '\0';
    return 0;
}



//Inicio modificacion Fernando***********
//***************************************
/**
\fn int iFnTomaPrimerPara()
\brief Deja el primer parametro dentro del buffer de teclado.
\return 0 si sale bien.
\date 06/09/2009
*/
void iFnTomaPrimerPara() {
	int iN=0,iJ=0;
	stCmd[0]='\0';
										
	while(stBuffer[iN]!=' '&&stBuffer[iN]!='\0')
	{
  		iN++;
	}
	
	if(stBuffer[iN] == '\0')
	{
		return;
	}
	
	iN++;
	
	while(stBuffer[iN]!=' '&&stBuffer[iN]!='\t'&&stBuffer[iN]!='\0')
	{
		stCmd[iJ]=stBuffer[iN];
		iJ++;
		iN++;
	}
	stCmd[iJ]='\0';
}

/**
\fn int iFnTomaNParametro(int iPos,char * stAux)
\brief Busca el N Parametro dentro del buffer de teclado
\param iPos Marca la posicion del N parametro
\param stAux Guarda en el auxiliar el valor del parametro
\return 0 si sale bien.
\date 06/09/2009
*/
void iFnTomaNParametro(int iPos,char * stAux) {
	int iN=0,iJ,iI;
	stAux[0]='\0';
										
	while(stBuffer[iN]!=' '&&stBuffer[iN]!='\0')
	{
  	iN++;
	}

	if(stBuffer[iN] == '\0')
	{
		return;
	}

	for(iI=0; iI<iPos; iI++)
  	{
	    	iN++;
	    	iJ=0;
		while(stBuffer[iN]!=' '&&stBuffer[iN]!='\t'&&stBuffer[iN]!='\0')
		{
			stAux[iJ]=stBuffer[iN];
			iJ++;
			iN++;
		}
  	}
	stAux[iJ]='\0';
}
//Fin modificacion Fernando***********
//***************************************

/**
\fn int iFnEjecutarBinario(char *stBinario, int iArgumento)
\brief Ejecuta de manera POSIX cualquier archivo ejecutable. Sergio Martin, 2010.
\param stBinario Indica el archivo ejecutable a instanciar
\param iArgumento Envia como parametro al ejecutable
\return 0 si sale bien.
\date 06/09/2009
*/
int iFnEjecutarBinario(char *stBinario, int iArgumento)
 {
    int iPid_Hijo = 0;
    int iShellActivo;
	long int liHeapSize;
    int i;
    
    char** pstArgv;
	char** pstEnvp;

    // Obtenemos ARGV
    pstArgv = pstFnObtenerArgumentos(stBuffer);
    if(pstArgv == -1) return -1;

	
	// Obtenemos Enviroment
	pstEnvp = pstFnEnvObtenerEnviroment();
    if(pstEnvp == -1) return -1;

	// Seteamos el tamaño del Heap de Usuario
	
   
   liHeapSize = iFnEnvObtenerValorNumericoDeVariable("TamanioHeapUsuario");
   if(liHeapSize <= 0)
     {
	    iFnImprimir("\n[!] Variable de entorno \"TamanioHeapUsuario\" no esta definida, utilizando tamanio de heap por defecto (100kb)");
		iFnSodiumCallgate(__FC_SETHEAPSIZE,100000,0);
		
	 }
   iFnSodiumCallgate(__FC_SETHEAPSIZE,liHeapSize,0);
   
   iPid_Hijo = fork();


     if(iPid_Hijo == 0) {
        if(execve(stBinario,pstArgv,pstEnvp) < 0) exit(1);
     }

    iShellActivo = iFnEnvCompararValorDeVariable("ModoShell","PASIVO"); // iShellActivo = Lo que devuelva la variable de entorno ModoShell

    if(iShellActivo == 0)  waitpid(iPid_Hijo,0,0); 
    
    return 0;
    
 }




/**
\fn int iFnObtenerCmd(char *stComando)
\brief Busca en el buffer de cCaracteres al comando
\param stComando Puntero a cCaracter a una cadena de texto que contiene el nombre del comando buscado.
\return 0 si sale bien.
\date 23/05/2009
*/
int iFnObtenerCmd(char *stComando, int *iArgumento, int *iArgumento2)
{
	char stArg[16];

	int iN = 0, iJ = 0, iK = 0;

	if (iCaracteresIngresados > 0) {

           while (((stBuffer[iN] == ' ') || (stBuffer[iN] == '\t')) && iN < TAMANIO_BUFFER_SHELL)
		{		
			iN++;	
		}		

		if (iN < TAMANIO_BUFFER_SHELL)	//si iN==TAMANIO_BUFFER_SHELL, no hay ningun comando para interpretar.
			//Se llegó al final del buffer y todos los cCaracteres eran
			//blancos
		{
			while ((stBuffer[iN] != ' ')
			       && (stBuffer[iN] != '\t')
			       && (stBuffer[iN] != '\0'))
                        {
				
			       stComando[iJ] = stBuffer[iN];
				iN++;
				iJ++;
			}
                    stComando[iJ] = '\0';
		}
		iJ = 0;
	        iN++;
		if(iN < TAMANIO_BUFFER_SHELL)
		{
			while((stBuffer[iN] != ' ') && (stBuffer[iN] != '\t') && (stBuffer[iN] != '\0'))
			{
				stArg[iJ]=stBuffer[iN];
				iN++;
				iJ++;
			}
			stArg[iJ]='\0';
		}
         //  if (((int)stBuffer[iN] >= 48) && ((int)stBuffer[iN] <= 51))  *iArgumento = (int)stBuffer[iN] - 48 ;
         //  else *iArgumento = 3;
         //stBuffer[iN+1] = '\0';
				 *iArgumento = iFnHtoi(stArg);
	iN++;
	iJ = 0;
		if(iN < TAMANIO_BUFFER_SHELL)
		{
			while((stBuffer[iN] != ' ') && (stBuffer[iN] != '\t') && (stBuffer[iN] != '\0'))
			{
				stArg[iJ]=stBuffer[iN];
				iN++;
				iJ++;
			}
			stArg[iJ]='\0';
		}
    	 *iArgumento2 = iFnCtoi(stArg);   
     		
	}
	 return 0;

}

/**
\fn int iFnEsCmdShell(char *stComando)
\brief Busca en el buffer de cCaracteres la existencia del comando pasado como parámetro
\param stComando Puntero a cCaracter a una cadena de texto que contiene el nombre del comando buscado.
\return Integer que indica la posicion inicial en el buffer donde se encontro el comando o -1 si no lo encontró.
\date 09/04/2009
*/
int iFnEsCmdShell(const char* stComando)
{
  int i = 0;
  int j = 0;
  while(stComando[i] == stCmd[i]) i++;
  while(stComando[j] != '\0') j++;
  if (i == j+1) return 1;
  return 0;
}



/**
\fn int iFnFuncionIdle()
\brief Llama a la tarea nula.
\return 0 si sale bien.
\date 06/09/2009
*/
int iFnFuncionIdle(){
        iFnImprimir("\nLlamando a la tarea nula... ");
	return idle();
}
	

/**
\fn void vFnMenuAyuda()
\brief Muestra la ayuda en pantalla, para más ayuda escriba ayuda.
\date 09/04/2009
*/
void vFnMenuAyuda()
{

        char cCaracter;
        int iCaracterLeido;
 
        iCaracterLeido = -1;
        cCaracter = '\0';
        
        iFnSodiumCallgate(__FC_CLS,0,0);
	iFnImprimir("\nSistemas Operativos - UNLaM");
	iFnImprimir
	    ("\n-------------------------------------------------------------------------------");
	iFnImprimir("\nCOMANDOS GENERALES");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>cls");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nLimpia la pantalla");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>desc [indice]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nDireccion donde se encuentra el descriptor indicado");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>dump [desde] [len]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nRealiza un vuelco de memoria en pantalla. \nIndicar Direccion inicial y cantidad de words");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>exec [opcion] [tam] [prioridad]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nCrea un proceso. Indicar su tamanio en bytes");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir
	    ("\nCmd>Execve [nombre_archivo] [parametros] [tam_bss] [prioridad]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nCrea un proceso a partir de un programa de prueba compilado en \nforma independiente. Indicar tamanio de BSS en bytes");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	PAUSA;		//cada quince lineas una pausa


	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>gdt");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nMuestra el contenido de las primeras 20 posiciones en la GDT");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>idt");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nMuestra el contenido de la IDT");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>kill [pid]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nRemueve el proceso de la memoria. Indicar Pid");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>mem");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nMuestra la cantidad de Memoria base y total del sistema");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>ps");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nLista los Procesos en memoria y su estado");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>stack [pid] [ring 0-2]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nMuestra el contenido del stack del proceso y ring de ejecucion especificado.");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>tss [pid]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nMuestra el contenido de la TSS y PCB del proceso indicado");

	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	PAUSA;


	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>syskill [pid] [sig]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nEnvia una senial a un proceso determinado.Seniales soportadas:\n SIGSTOP, SIGCONT, SIGKILL, SIGTERM, SIGALARM");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>ver");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nVersion del sistema operativo");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>winm");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nOculta o restaura la ventana de procesos de usuario");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>ls");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nMuestra los archivos presentes en el directorio actual");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>reboot");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nReinicia el sistema");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>set");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nImprime la lista de Variables de entorno");
    iFnImprimir("\nPara crear una variable de entorno debe usarse la siguiente sintaxis");
	iFnImprimir("\nVARIABLE=VALOR");
	iFnImprimir("\nPara borrar una variable de entorno debe usarse la siguiente sintaxis");
	iFnImprimir("\nVARIABLE=\nDejando vacia la parte derecha de la asignacion");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	PAUSA;

	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>planif [subcomando] [parametros]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nPermite la modificacion del algoritmo de planificacion.\nDependiendo del subcomando"
	     " seleccionado, se obtienen diferentes resultados.\nTipee [planif ayuda] o [planif] para mas informacion");

	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>lote [subcomando] [parametros]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir
	    ("\nPermite la creacion de conjuntos de procesos que se dispararan\nde forma simultanea.\n"
	     "Dependiendo del subcomando seleccionado, se obtienen diferentes resultados.\nTipee [lote ayuda] o [lote] para mas informacion");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>sumafpu numero1 numero");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nSuma dos numeros flotantes y muestra el resultado por pantalla");

	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>cambiateclado [NUMERO_DISTRIBUCION | CODIGO_DISTRIBUCION]");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nCambia la configuracion del teclado. Si se ejecuta sin parametros muestra las distribuciones disponibles");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	PAUSA;


	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>ejecutar ARCHIVO");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nEjecuta ARCHIVO.BIN (se debe omitir la extension en la invocacion). Si el archivo pasado por parametro no es un ejecutable correctamente compilado, los resultados son impredecibles");

	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	

iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>listpart");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nLista las particiones activas, su tamanio y si estan utilizadas o libres.");

iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>listporc");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nLista los porcentajes de asignacion para usuario de tamanios de particion fija proporcional");

iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>borrarpf");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nBorra la ultima entrada en la lista de porcentajes para particiones fijas proporcionales para usuario");
PAUSA;
iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>agregarpf PORCENTAJE");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nAgrega una entrada en la lista de porcentajes para particiones fijas proporcionales para usuario");

iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>listaesp");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nMuestra la lista de programas esperando por tener memoria para iniciarse.");
	
iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO_BRILLANTE);
	iFnImprimir("\nCmd>exit");
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	iFnImprimir("\nSale del proceso de shell. Util si fué invocado por otro proceso shell.");

PAUSA;
	iFnSodiumCallgate(__FC_COLOR,HWND_COMANDO, BLANCO);
	
}

/**
\fn void vFnMenuPlanif()
\brief llama al system call correspondiente de acuerdo a los parametros pasados a planif por linea de comandos
\date 12/08/2009
*/

void vFnMenuPlanif()
{
	int iN=0,iJ=0;

	while(stBuffer[iN]!=' '&&stBuffer[iN]!='\t'&&stBuffer[iN]!='\0') iN++;
	
	if(stBuffer[iN]!=' ') iFnImprimir("\nError de parametros\nLas opciones son aplicar, cambiar [planif], defecto, mostrar o set\n");

	iN++;
	
	while(stBuffer[iN] != ' ' && stBuffer[iN] != '\t' && stBuffer[iN] != '\0')
	{	
		stCmd[iJ]=stBuffer[iN];
		iJ++;
		iN++;
	}
	stCmd[iJ]='\0';
	
	if(iFnEsCmdShell("aplicar")) iFnSodiumCallgate(__FC_PLANIF,0,1);
	else
	{
		if(iFnEsCmdShell("cambiar"))
		{
			if(stBuffer[iN] != ' ') iFnImprimir("\nError de parametros\nLas opciones son aplicar, cambiar [planif], defecto, mostrar o set\n");
			else
			{
				iJ=0;
				iN++;
				while(stBuffer[iN] != ' ' && stBuffer[iN] != '\t' && stBuffer[iN] != '\0')
				{	
					stCmd[iJ]=stBuffer[iN];
					iJ++;
					iN++;
				}
				stCmd[iJ]='\0';
				if(iFnEsCmdShell("RR")) iFnSodiumCallgate(__FC_PLANIF,1,2);
				else if(iFnEsCmdShell("BTS")) iFnSodiumCallgate(__FC_PLANIF,2,2);
				else if(iFnEsCmdShell("FIFO")) iFnSodiumCallgate(__FC_PLANIF,3,2);
				else iFnImprimir("\nPlanificador incorrecto\nLas opciones son RR, BTS o FIFO\n");
			}
		}
		else
		{
			if(iFnEsCmdShell("defecto")) iFnSodiumCallgate(__FC_PLANIF,0,3);
			else
			{
				if(iFnEsCmdShell("mostrar")) iFnSodiumCallgate(__FC_PLANIF,0,4);
				else
				{
					if(iFnEsCmdShell("set"))
					{
						if(stBuffer[iN] != ' ') iFnImprimir("\nError de parametros\nEl formato es planif set [variable]=[valor]\n");
						else
						{
							iJ=0;
							iN++;
							while(stBuffer[iN]!=' '&&stBuffer[iN]!='\t'&&stBuffer[iN]!='\0')
							{
								stCmd[iJ]=stBuffer[iN];
								iJ++;
								iN++;
							}
							stCmd[iJ]='\0';
							iFnSodiumCallgate(__FC_PLANIF,(int)stCmd,5);
						}
					}
					else iFnImprimir("\nError de parametros\nLas opciones son aplicar, cambiar [planif], defecto, mostrar o set\n");
				}
			}
		}
	}
}




	
void vFnMenuDescUsr(int iPar)
{
	char cCaracter;
        int iCaracterLeido = -1;
	iFnSodiumCallgate(__FC_DESC,iPar,1);
	PAUSA;
	iFnSodiumCallgate(__FC_DESC,iPar,2);
	PAUSA;
	iFnSodiumCallgate(__FC_DESC,iPar,3);
	PAUSA;
	return;
}	

void vFnMenuDumpUsr(int iArg1, int iArg2)
{
	char cCaracter;
        int iCaracterLeido = -1;
	int i;
	if (iArg1 >= 0 && iArg2 > 0)
	{
		iFnImprimir("\nIniciando vuelco de memoria de %d dwords, desde %d...",iArg2,iArg1);

		for (i = 0; i < iArg2; i++) {
			iFnSodiumCallgate(__FC_DUMP,iArg1,i);
			if (i%15 == 0 && i > 0)
			{
				PAUSA_BREAK3; //Cada 15 lineas
			}
		}
		iFnImprimir("\nFin");
	} else {
		iFnImprimir("\nError, argumento(s) incorrecto(s).\nForma de uso: Cmd>dump [dir mem] [intervalo]");
	}
}	




/**
\fn int iFnCompletarComando(const char* stCadena)
\brief Utilizado por vFnAutocompletar para saber si el comando responde a lo ingresado.
\param stCadena Es el comando a comparar
\return 0 si no corresponde. 1 si corresponde.
\date 18/10/2009
*/
int iFnCompletarComando(const char* stCadena)
  {
    char stTemp[2];
    int i;

    stTemp[0] = (char)TECLA_BACKSPACE;
    stTemp[1] = '\0';

    if(iFnNumStrcmp(stBuffer,stCadena) == iCaracteresIngresados)
     {
        for(i = 0; i < iCaracteresIngresados; i++) iFnImprimir("%s",stTemp);
        iFnStrcpy(stBuffer,stCadena);
        iCaracteresIngresados = iFnStrlen(stCadena);
        iFnImprimir("%s",stCadena);
        return 1;
     }
    return 0;
  }

/**
\fn void vFnAutocompletar()
\brief Autocompleta el comando ingresado parcialmente
\date 18/10/2009
*/
void vFnAutocompletar()
{

   if (iCaracteresIngresados == 0) return;
 
	if(iFnCompletarComando("ayuda")) return;
	if(iFnCompletarComando("bitmap")) return;
	if(iFnCompletarComando("verSem")) return;
	if(iFnCompletarComando("verShm")) return;
	if(iFnCompletarComando("check")) return;
	if(iFnCompletarComando("sysgetpid")) return;
	if(iFnCompletarComando("syswaitpid")) return;
	if(iFnCompletarComando("syskill")) return;
	if(iFnCompletarComando("planif")) return;
	if(iFnCompletarComando("lote")) return;
	if(iFnCompletarComando("log")) return;
	if(iFnCompletarComando("pcb")) return;
	if(iFnCompletarComando("leer")) return;
	if(iFnCompletarComando("idle")) return;
	if(iFnCompletarComando("reboot")) return;
	if(iFnCompletarComando("cambiateclado")) return;
	if(iFnCompletarComando("cls")) return;
	if(iFnCompletarComando("desc")) return;
	if(iFnCompletarComando("dump")) return;
	if(iFnCompletarComando("ejecutar")) return;
	if(iFnCompletarComando("stack")) return;
	if(iFnCompletarComando("execve")) return;
	if(iFnCompletarComando("exec")) return;
	if(iFnCompletarComando("gdt")) return;
	if(iFnCompletarComando("idt")) return;
	if(iFnCompletarComando("kill")) return;
	if(iFnCompletarComando("cd")) return;
	if(iFnCompletarComando("ls")) return;
	if(iFnCompletarComando("rm")) return;
	if(iFnCompletarComando("exit")) return;
	if(iFnCompletarComando("mem")) return;
	if(iFnCompletarComando("write")) return;
	if(iFnCompletarComando("pag")) return;
	if(iFnCompletarComando("yield")) return;
	if(iFnCompletarComando("interval")) return;
	if(iFnCompletarComando("fd")) return;
	if(iFnCompletarComando("ps")) return;
	if(iFnCompletarComando("segs")) return;
	if(iFnCompletarComando("set")) return;
	if(iFnCompletarComando("sumafpu")) return;
	if(iFnCompletarComando("tss")) return;
	if(iFnCompletarComando("ver")) return;
	if(iFnCompletarComando("winm")) return;
	if(iFnCompletarComando("listpart")) return;
	if(iFnCompletarComando("listporc")) return;
	if(iFnCompletarComando("borrarpf")) return;
	if(iFnCompletarComando("agregarpf")) return;
	if(iFnCompletarComando("resetpf")) return;
	if(iFnCompletarComando("listaesp")) return;
}
